﻿using System;
using System.Collections.Generic;
using System.Net.Sockets;
using UnityEngine;

namespace Script.Net
{
    /// <summary>
    /// 客户端Socket的封装
    /// 接受网络的消息
    /// 交由NetManager
    /// </summary>
    public class ClientPeer
    {
        private readonly Socket socket;

        private readonly string ip;
        private readonly int port;

        public ClientPeer(string ip, int port)
        {
            try
            {
                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                this.ip = ip;
                this.port = port;
                Connect();
            }
            catch (Exception e)
            {
                Debug.Log(e.Message);
                throw;
            }
        }

        private void Connect()
        {
            try
            {
                socket.Connect(ip, port);
                Debug.Log("连接服务器成功");
                // 开始异步接受数据
                startReceive();
            }
            catch (Exception e)
            {
                Debug.LogError(e.Message);
            }
        }


        #region 接受数据

        /// <summary>
        /// 本部分处理完成后交由其他部分处理的消息
        /// </summary>
        public readonly Queue<SocketMsg> SocketMsgQueue = new Queue<SocketMsg>();

        /// <summary>
        /// 接受的数据缓冲区
        /// </summary>
        private readonly byte[] receiveBuffer = new byte[1024];

        /// <summary>
        /// 一但接受到数据 就缓存到缓存里面
        /// </summary>
        private List<byte> dataCache = new List<byte>();

        private bool isProcessReceive;


        /// <summary>
        /// 异步接收服务器数据的方法
        /// </summary>
        private void startReceive()
        {
            if (socket != null && (socket == null && socket.Connected == false))
            {
                Debug.LogError("没有连接成功，无法发送数据");
                return;
            }

            socket?.BeginReceive(receiveBuffer, 0, 1024, SocketFlags.None, receiveCallBack, socket);
        }

        /// <summary>
        /// 收到消息的回调
        /// </summary>
        private void receiveCallBack(IAsyncResult ar)
        {
            try
            {
                int length = socket.EndReceive(ar);
                byte[] tmpByteArray = new byte[length];
                Buffer.BlockCopy(receiveBuffer, 0, tmpByteArray, 0, length);

                //处理收到的数据
                dataCache.AddRange(tmpByteArray);
                if (isProcessReceive == false)
                    processReceive();

                startReceive();
            }
            catch (Exception e)
            {
                Debug.LogError(e.Message);
            }
        }

        /// <summary>
        /// 处理收到的数据包
        /// </summary>
        private void processReceive()
        {
            isProcessReceive = true;

            byte[] data = EncodeTool.DecodePacket(ref dataCache);

            if (data == null)
            {
                isProcessReceive = false;
                return;
            }

            SocketMsg msg = EncodeTool.DecodeMsg(data);

            // 存储消息 等待处理
            SocketMsgQueue.Enqueue(msg);

            Debug.Log(msg.Value);

            // 尾递归
            processReceive();
        }

        #endregion

        #region 发送数据

        public void Send(int opCode, int subCode, object value)
        {
            SocketMsg msg = new SocketMsg(opCode, subCode, value);

            Send(msg);
        }

        public void Send(SocketMsg msg)
        {
            byte[] data = EncodeTool.EncodeMsg(msg);
            byte[] packet = EncodeTool.EncodePacket(data);


            try
            {
                socket.Send(packet);
            }
            catch (Exception e)
            {
                Debug.LogError(e.Message);
            }
        }

        #endregion
    }
}